package com.hitqz.robot.daemon.quartz.controller;

import cn.hutool.extra.spring.SpringUtil;
import com.google.common.cache.Cache;
import com.hitqz.robot.api.business.dto.RobotClientSummaryDto;
import com.hitqz.robot.common.core.util.R;
import com.hitqz.robot.daemon.quartz.model.DgAgvStatusDto;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.List;

/**
 * @author xupkun
 * @date 2025/4/16
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/km/agv/dg")
@Tag(name = "昆明北车辆段-数字孪生接口")
@Slf4j
public class KmDgTwinController {

    private static final String EVENT_NAME = "recent_robot\n";

    private static final int TICKET_COUNT = 5;
    private static final Duration INTERVAL_DURATION = Duration.ofSeconds(3);
    private static final Duration TIMEOUT_DURATION = Duration.ofSeconds(5);



    @GetMapping(value = "agv", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<R<List<DgAgvStatusDto>>>> recentTickets() {
        return Flux.interval(INTERVAL_DURATION)
                .flatMap(sequence -> buildServerSentEvent(sequence), 1)
                .doOnCancel(() -> log.info("Subscription cancelled"))
                .doOnError(error -> log.error("Error in recentTickets: {}", error.getMessage()))
                .doOnSubscribe(subscription -> log.info("Subscription started"));
    }



    private Mono<ServerSentEvent<R<List<DgAgvStatusDto>>>> buildServerSentEvent(long sequence) {
        return Mono.fromCallable(() -> this.getStatus())
                .map(tickets -> createEvent(sequence, tickets))
                .onErrorResume(e -> {
                    log.error("Error fetching dg robot status: {}", e.getMessage());
                    return Mono.just(createEmptyEvent(sequence));
                })
                .timeout(TIMEOUT_DURATION, Mono.just(createEmptyEvent(sequence)));
    }


    private ServerSentEvent<R<List<DgAgvStatusDto>>> createEvent(long sequence, List<DgAgvStatusDto> dgAgvStatusDtos) {
        return ServerSentEvent.<R<List<DgAgvStatusDto>>>builder()
                .id(String.valueOf(sequence))
                .event(EVENT_NAME)
                .data(R.ok(dgAgvStatusDtos))
                .build();
    }

    private ServerSentEvent<R<List<DgAgvStatusDto>>> createEmptyEvent(long sequence) {
        return ServerSentEvent.<R<List<DgAgvStatusDto>>>builder()
                .id(String.valueOf(sequence))
                .event(EVENT_NAME)
                .data(R.ok(List.of()))
                .build();
    }


    private List<DgAgvStatusDto> getStatus() {
        Cache<String, RobotClientSummaryDto> robotClientSummaryDtoCache = SpringUtil.getBean("robotCache");
        List<DgAgvStatusDto> list = Lists.newArrayList();
        //DgAgvStatusDto dgAgvStatusDto = new DgAgvStatusDto();
        //dgAgvStatusDto.setAgvSn("5401");
        //dgAgvStatusDto.setJackStatus(1);
        //dgAgvStatusDto.setPosX(25.843);
        //dgAgvStatusDto.setPosY(-19.461);
        //dgAgvStatusDto.setYaw(-90.395);
        //list.add(dgAgvStatusDto);
        for (RobotClientSummaryDto dto: robotClientSummaryDtoCache.asMap().values()) {
            DgAgvStatusDto dgAgvStatusDto = new DgAgvStatusDto();
            dgAgvStatusDto.setAgvSn(dto.getClientId());
            dgAgvStatusDto.setPosX(dto.getPosition().getLaserPos().getX());
            dgAgvStatusDto.setPosY(dto.getPosition().getLaserPos().getY());
            dgAgvStatusDto.setYaw(dto.getPosition().getLaserPos().getYaw());
            dgAgvStatusDto.setJackStatus(
                    dto.getStatus().getTaskStatus() == 2
                            ? 8 : transportJackStatus(dto.getStatus().getJackStatus()));
            list.add(dgAgvStatusDto);
        }
        return list;
    }





    public int transportJackStatus(int jackStatus) {
        int sendStatus = 0;
        switch (jackStatus) {
            case 0:
                sendStatus = 6; // 上升中
                break;
            case 1:
                sendStatus = 2; // 顶部
                break;
            case 2:
                sendStatus = 7; // 下降中
                break;
            case 3:
                sendStatus = 1; // 底部
                break;
            default:
                log.warn("未知的顶升状态码: {}", jackStatus);
        }

        return sendStatus;
    }

}
